/*
 * MapContextMenuManager.java
 *
 * Created on November 9, 2008, 9:53 PM
 *
 * Copyright 2008 David D. Emory
 *
 * This file is part of Five Points. See <http://www.fpdev.org> for
 * additional information regarding the project.
 *
 * Five Points is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Five Points is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Five Points.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.fpdev.apps.rtemaster.gui.map;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import org.fpdev.core.basenet.BLink;
import org.fpdev.core.basenet.BNode;
import org.fpdev.apps.rtemaster.RMEvent;
import org.fpdev.apps.rtemaster.RouteMaster;
import org.fpdev.apps.rtemaster.EventTypes;

/**
 *
 * @author demory
 */
public class MapContextMenuManager implements ActionListener {

  private RouteMaster av_;
  private MapPanel map_;

  private int mx_, my_;

  //private Map<AViewGUI.Mode, JPopupMenu> linkMenus_, nodeMenus_, defaultMenus_;
  //private JPopupMenu nodeContextMenu_, linkContextMenu_, defaultContextMenu_;
  private BNode activeNode_;
  private BLink activeLink_;

  private enum CMAction {
    SET_TRIP_START("Set as Trip Start"),
    SET_TRIP_END("Set as Trip End"),
    DELETE_NODE("Delete Node"),
    LINK_PROPERTIES("Edit This Link's Properties"),
    LINK_SCEN_TYPES("Edit Link's Scenario-Specific Types"),
    DELETE_LINK("Delete Link"),
    SPLIT_LINK("Split Link Here"),
    STITCH_CONNECTING_LINKS("Stitch Links Connected at Node"),
    ADD_SHAPEPOINT("Add Shapepoint Here"),
    RECENTER("Recenter Here"),
    LINKS_PROPERTIES("Edit Selected Link(s) Properties"),
    LINKS_SCEN_TYPES("Edit Selected Link(s) Scenario-Specific Types"),
    CLEAR_SELECTED("Clear Selected Node(s)/Link(s)"),
    QUERY_LINK_FOR_ROUTES("Query Link for Routes");
    
    private String menuText_;
    
    CMAction(String txt) {
      menuText_ = txt;
    }
    
    public String getText() { return menuText_; }

  };

  public MapContextMenuManager(RouteMaster av, MapPanel map) {
    av_ = av;
    map_ = map;
  }

  private JPopupMenu initMenu(Collection<CMAction> actions) {
    JPopupMenu menu = new JPopupMenu();
    for (CMAction action : actions)
       menu.add(new ContextMenuItem(action));
    return menu;
  }

  public void showNodeMenu(BNode node, int x, int y) {

    List<CMAction> actions = new LinkedList<CMAction>();
    switch(av_.getGUI().getMode()) {
      case ANALYSIS:
        actions.addAll(Arrays.asList(new CMAction[] { CMAction.SET_TRIP_START, CMAction.SET_TRIP_END }));
        break;
      case MAP:
        actions.add(CMAction.DELETE_NODE);
        int degree = av_.getEngine().getBaseNet().linkCount(node);
        if(degree > 0 && degree % 2 ==0)
          actions.add(CMAction.STITCH_CONNECTING_LINKS);
        break;
    }

    if(!actions.isEmpty()) {
      activeNode_ = node;
      mx_ = x; my_ = y;
      initMenu(actions).show(map_, x, y);
    }

  }

  public void showLinkMenu(BLink link, int x, int y) {
    
    List<CMAction> actions = new LinkedList<CMAction>();
    switch(av_.getGUI().getMode()) {
      case ANALYSIS:
        actions.add(CMAction.QUERY_LINK_FOR_ROUTES);
        break;
      case MAP:
        actions.addAll(Arrays.asList(new CMAction[] { CMAction.LINK_PROPERTIES, CMAction.LINK_SCEN_TYPES, CMAction.SPLIT_LINK, CMAction.ADD_SHAPEPOINT, CMAction.DELETE_LINK }));
        if(!map_.getSelectedLinks().isEmpty())
          actions.addAll(Arrays.asList(new CMAction[] { CMAction.LINKS_PROPERTIES, CMAction.LINKS_SCEN_TYPES }));
        if(!map_.getSelectedLinks().isEmpty() || !map_.getSelectedNodes().isEmpty())
          actions.add(CMAction.CLEAR_SELECTED);
        break;
    }
    
    if(!actions.isEmpty()) {
      activeLink_ = link;
      mx_ = x; my_ = y;
      initMenu(actions).show(map_, x, y);
    }

  }

  public void showDefaultMenu(int x, int y) {

    List<CMAction> actions = new LinkedList<CMAction>();
    actions.add(CMAction.RECENTER);
    switch(av_.getGUI().getMode()) {
      case MAP:
        if(!map_.getSelectedLinks().isEmpty())
          actions.addAll(Arrays.asList(new CMAction[] { CMAction.LINKS_PROPERTIES, CMAction.LINKS_SCEN_TYPES }));
        if(!map_.getSelectedLinks().isEmpty() || !map_.getSelectedNodes().isEmpty())
          actions.add(CMAction.CLEAR_SELECTED);
        break;
    }

    if(!actions.isEmpty()) {
      mx_ = x; my_ = y;
      initMenu(actions).show(map_, x, y);
    }

  }

  public void actionPerformed(ActionEvent e) {
    if (e.getSource() instanceof ContextMenuItem)
      contextMenuItemSelected(((ContextMenuItem) e.getSource()).getCMAction());
  }

  private void contextMenuItemSelected(CMAction action) {
    RMEvent ev = null;
    
    switch (action) {
      case SET_TRIP_START:
        ev = new RMEvent(EventTypes.MCLICK_AN_TRIP_START);
        ev.setProperty("node", activeNode_);
        break;
      case SET_TRIP_END:
        ev = new RMEvent(EventTypes.MCLICK_AN_TRIP_END);
        ev.setProperty("node", activeNode_);
        break;
      case DELETE_NODE:
        ev = new RMEvent(EventTypes.MCLICK_MAP_DELETE_NODE);
        ev.setProperty("node", activeNode_);
        break;
      case LINK_PROPERTIES:
        ev = new RMEvent(EventTypes.MAPMENU_EDIT_LINK_PROPERTIES);
        ev.setProperty("link", activeLink_);
        break;
      case LINK_SCEN_TYPES:
        ev = new RMEvent(EventTypes.MAPMENU_EDIT_SCEN_LINK_TYPES);
        ev.setProperty("link", activeLink_);
        break;
      case DELETE_LINK:
        ev = new RMEvent(EventTypes.MCLICK_MAP_DELETE_LINK);
        ev.setProperty("link", activeLink_);
        break;
      case SPLIT_LINK: // split link
        ev = new RMEvent(EventTypes.MCLICK_MAP_SPLIT_LINK);
        ev.setProperty("link", activeLink_);
        ev.setProperty("x", map_.getCanvas().getCC().xToWorld(mx_));
        ev.setProperty("y", map_.getCanvas().getCC().yToWorld(my_));
        break;
      case STITCH_CONNECTING_LINKS:
        ev = new RMEvent(EventTypes.MCLICK_MAP_STITCH_LINKS);
        ev.setProperty("node", activeNode_);
        break;
      case RECENTER:
        map_.recenter();
        break;
      case LINKS_PROPERTIES:
        ev = new RMEvent(EventTypes.MAPMENU_EDIT_LINK_PROPERTIES);
        break;
      case LINKS_SCEN_TYPES:
        ev = new RMEvent(EventTypes.MAPMENU_EDIT_SCEN_LINK_TYPES);
        break;
      case CLEAR_SELECTED:
        ev = new RMEvent(EventTypes.MAPMENU_CLEAR_SELECTED);
        break;
      case QUERY_LINK_FOR_ROUTES:
        ev = new RMEvent(EventTypes.MCLICK_AN_QUERY_LINK);
        ev.setProperty("link", activeLink_);
        break;
    }

    if (activeNode_ != null) activeNode_ = null;
    if (activeLink_ != null) activeLink_ = null;


    if(ev != null) av_.fireEvent(ev);

  }

  private class ContextMenuItem extends JMenuItem {

    private CMAction action_;

    public ContextMenuItem(CMAction action) {
      super(action.getText());
      addActionListener(MapContextMenuManager.this);
      action_ = action;
    }

    public CMAction getCMAction() { return action_; }
  }

}
